package core

import (
	"encoding/json"
	"strconv"
	"time"
)

type Conf struct {
	HTTPServerPort int
	UDPServerPort  int
	TCPServerPort  int
	AudioFilePath  string
	TestMode       bool
}

func (c *Conf) String() string {
	return "http-port[" + strconv.Itoa(c.HTTPServerPort) +
		"],udp-port[" + strconv.Itoa(c.UDPServerPort) +
		"],tcp-port[" + strconv.Itoa(c.TCPServerPort) +
		"],audio-file-path[" + c.AudioFilePath + "],test-mode[" + strconv.FormatBool(c.TestMode) + "]"
}

type Ctx struct {
	DevCache  map[string]*Dev
	TaskCache map[int]*Task
	S0        *UDPServer
	S1        *TCPServer
	Conf      *Conf
}

var ctx *Ctx

func InitCtx(conf *Conf) {
	InitUDPServer("0.0.0.0", conf.UDPServerPort)
	S0 := GetUDPServer()

	InitTCPServer("0.0.0.0", conf.TCPServerPort)
	S1 := GetTCPServer()

	ctx = &Ctx{
		DevCache:  make(map[string]*Dev),
		TaskCache: make(map[int]*Task),
		S0:        S0,
		S1:        S1,
		Conf:      conf,
	}

	go ctx.devCacheTimer()
}

func GetCtx() *Ctx {
	return ctx
}

func (c *Ctx) devCacheTimer() {
	for {
		for _, dev := range c.DevCache {
			if dev != nil {

				now := time.Now().Unix() / 1e6

				// send tcp status msg
				msg := &DevStatusMsg{
					MsgType:        1,
					DevID:          dev.DevID,
					IP:             dev.IP,
					OnSpeech:       false,
					OnPlaying:      false,
					Online:         false,
					Mode:           dev.Mode,
					LockedByUserID: 0,
					Time:           dev.Ts,
				}

				if dev.Ts > now-60000 { // online
					msg.Online = true
				}

				if dev.CurrentTask != nil { // onPlaying
					msg.OnPlaying = true
				}

				if dev.Locked { // onSpeech

					// auto close speech
					if dev.SpeechPacketTime != 0 && now-dev.SpeechPacketTime > 10000 {
						dev.Locked = false
						dev.LockedByLevel = 0
						dev.LockedByUserID = 0
						dev.SpeechPacketTime = 0
					} else {
						msg.OnSpeech = true
						msg.LockedByUserID = dev.LockedByUserID
					}
				}

				// keep dev working status right

				if dev.Mode != 3 { // change mode
					dev.ChangeMode()
				}

				if !msg.OnPlaying && !msg.OnSpeech {
					dev.Heartbeat()
				} else if dev.VoicePower != 1 { // working, must open sound
					dev.OpenSound()
				}

				b, _ := json.Marshal(msg)
				ctx.S1.Broadcast(b)
			}
		}
		time.Sleep(time.Second * 3)
	}
}
